package com.lijing.CircleLinkedList;

public class CircleSingleLinkedList {
    private Boy first = new Boy(-1);//创建一个first节点，当前没有编号

    //添加节点，构成环形链表
    public void addBoy(int nums){
        //nums校验
        if(nums < 1){
            System.out.println("nums的值不正确！至少大于1");
            return;
        }
        Boy curBoy = null;//辅助指针，帮助构建环形链表，其实是指向了当前环形链表的最后一个节点，curBoy.next = first
        for (int i = 1; i <= nums; i++) {
            //根据编号创建小孩节点
            Boy boy = new Boy(i);
            //如果是第一个小孩
            if(i==1){
                first = boy;
                boy.setNext(first);
                curBoy = first;
            }else {
                curBoy.setNext(boy);
                boy.setNext(first);
                curBoy = boy;
            }
        }

    }

    //遍历节点
    public void showBoy(){
        //判断链表是否为空
        if(first == null){
            System.out.println("链表为空！");
            return;
        }
        Boy curBoy = first;
        while(true){
            System.out.printf("小孩的编号%d\n",curBoy.getNo());
            if (curBoy.getNext() == first){//已经遍历完毕
                break;
            }
            curBoy = curBoy.getNext();
        }
    }

    public void listBoy(){
        //判断链表是否为空
        if(first == null){
            System.out.println("list is empty!");
        }
        Boy curBoy = first;
        System.out.println("curBoy is " + curBoy.getNo());
        while (curBoy.getNext() != first){
            System.out.println("curBoy is " + curBoy.getNext().getNo());
            curBoy = curBoy.getNext();
        }
    }

    /**
     * 计算出队编号
     * @param startNo 从第几个开始数数
     * @param countNo 数几下
     * @param nums 最出由多少小孩在圈
     */
    public void printOutBoy(int startNo, int countNo, int nums){//从第k个人开始报数，数m下的那个节点出链表
        //判断链表是否为空
        if (first == null || startNo < 1 || startNo > nums){
            System.out.println("您的参数输入有误，请重新输入！");
        }
        //首先将helper指向first前一个节点
        Boy helper = first;
        while (true) {
            if (helper.getNext() == first) {//说明helper指向最后一个节点
                break;
            }
            helper = helper.getNext();
        }
        //将helper和first同时向前移动startNo-1次,找到报数的起始位置
        for (int i = 0; i < startNo-1; i++) {
            first = first.getNext();
            helper = helper.getNext();
        }
        //做一个循环，每报数countNo次，即将helper和first同时向前移动countNo-1次，然后将first出圈
        while (true){
            if (helper == first){//说明圈中只有一个节点
                break;
            }
            for (int j = 0; j < countNo-1; j++) {
                first = first.getNext();
                helper = helper.getNext();
            }
            System.out.printf("小孩%d出圈\n",first.getNo());
            first = first.getNext();
            helper.setNext(first);
        }
        System.out.printf("最后一个在圈里的小孩是%d\n",first.getNo());
    }




}
